from wechatpy import WeChatClientException
from collections import defaultdict
from wechatpy.enterprise import *
from extensions.common.base import *
from django.utils import timezone
from django.core.cache import cache
import logging

logger = logging.getLogger("django")


class WechatPy:
    def __init__(self):
        self.cropid = settings.EXTERPRISE_WECHAT['cropid']
        self.secret = settings.EXTERPRISE_WECHAT['secret']
        self.client = WeChatClient(settings.EXTERPRISE_WECHAT['cropid'],
                                   settings.EXTERPRISE_WECHAT['secret'])

    def get_access_token(self):
        """
        获取企业微信的 access token
        return: access token
        """
        # cache_key = 'erp_server.apps.callback.en_wechat.access_token'
        # access_token = cache.get(cache_key)
        # if access_token:
        #     return access_token

        try:
            access_token = self.client.access_token
            # cache.set(cache_key, access_token, timeout=7000)
            return access_token
        except Exception as e:
            logger.error(f"Failed to get access token: {e}")
            return None

    def get_applyDetail(self, spno):
        """
           获取审批详情
           spno 审批编号
           return: 审批详情数据
       """
        token = self.get_access_token()
        data = {'sp_no': spno}
        url = f"https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovaldetail?access_token={token}"
        try:
            response = self.client.post(url, json=data)
            if response['errcode'] == 0:
                # 如果返回的 errcode 是 0，表示请求成功
                return response
            else:
                # 处理错误情况
                error_message = f"WeChat API Error: {response['errcode']} - {response['errmsg']}"
                print(error_message)
                # 可以根据实际情况进行错误处理，比如记录日志、返回特定错误信息等
                return None
        except WeChatClientException as e:
            # 处理 WeChatClientException 异常
            print({'error': f"get_applyDetailWeChat Client Exception: {e}"})
            return None
        except Exception as e:
            # 处理其他可能的异常
            print({'error': f"get_applyDetailException occurred: {e}"})
            return None

    def get_Template(self, template_id):
        """
           获取审批模板
           template_id 模板编号
           return: 模板数据
       """
        # 创建 WeChatClient 实例
        token = self.get_access_token()
        data = {'template_id': template_id}
        url = f"https://qyapi.weixin.qq.com/cgi-bin/oa/gettemplatedetail?access_token={token}"

        try:
            # 发起 POST 请求
            response = self.client.post(url, data=data)
            # 检查响应是否正常
            if response['errcode'] == 0:
                return response
            else:
                # 处理 API 错误
                error_message = f"WeChat API Error: {response['errcode']} - {response['errmsg']}"
                print(error_message)
                return None
        except WeChatClientException as e:
            # 处理 WeChatClientException 异常
            print({'error': f"get_TemplateWeChat Client Exception: {e}"})
            return None
        except Exception as e:
            # 处理其他可能的异常
            print({'error': f"get_TemplateException occurred: {e}"})
            return None

    def get_user(self, user_id):
        """
           获取用户信息
           user_id 用户id
           return: 用户数据
       """
        token = self.get_access_token()
        url = f"https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token={token}&userid={user_id}"

        try:
            # 发起 GET 请求
            response = self.client.get(url)
            # 检查响应是否正常
            if response['errcode'] == 0:
                return response
            else:
                # 处理 API 错误
                error_message = f"get_userWeChat API Error: {response['errcode']} - {response['errmsg']}"
                print(error_message)
                return None
        except WeChatClientException as e:
            # 处理 WeChatClientException 异常
            print({'error': f"get_userWeChat Client Exception: {e}"})
            return None
        except Exception as e:
            # 处理其他可能的异常
            print({'error': f"get_userException occurred: {e}"})
            return None

    def get_template_data(self, template_data, root_instance):
        controls = template_data['template_content']['controls']
        # 获取第一层的id和对应的值
        h = {}
        for control in controls:
            title = control['property']['title'][0]['text']
            id = control['property']['id']
            h[id] = title
        primarkey_id = []
        tree_list = []
        # 解析
        for control in controls:
            id = control['property']['id']
            title = control['property']['title'][0]['text']
            con = control['property']['control']
            to_type = None
            if con == 'Selector':
                to_type = 6
            if id not in primarkey_id:
                tree_list.append({'id': id, 'title': title, 'parent_id': root_instance.id, 'to_type': to_type})
                primarkey_id.append(id)
            if con == 'Selector':
                selector = control['config']['selector']
                options = control['config']['selector']['options']
                for option in options:
                    to_type = None
                    op_key = option['key']
                    value = option['value'][0]['text']
                    if value == "无":
                        to_type = 6
                    if op_key not in primarkey_id:
                        primarkey_id.append(op_key)
                        tree_list.append(
                            {'id': op_key, 'title': value, 'parent_id': id, 'to_type': to_type})
                op_relations = selector['op_relations']

                for op_relation in op_relations:
                    relation_list = op_relation['relation_list']
                    op_relation_key = op_relation['key']
                    for relation in relation_list:
                        to_type = None
                        related_control_id = relation['related_control_id']
                        if 'Selector' in related_control_id:
                            to_type = 6
                        elif 'Number' in related_control_id:
                            to_type = 3
                        if related_control_id not in primarkey_id:
                            primarkey_id.append(related_control_id)
                            tree_list.append(
                                {'id': related_control_id, 'title': h[related_control_id], 'parent_id': op_relation_key,
                                 'to_type': to_type})
        return tree_list

    # def create_templatetree(self, template_id):
    #     '''创建模板'''
    #     template_data = self.get_Template(template_id)
    #     if not template_data:
    #         return None
    #
    #     with transaction.atomic():
    #
    #         # 存储,创建根节点
    #         root_data = {'parent_id': None, 'title': template_data['template_names'][0]['text'], 'id': template_id,
    #                      'to_type': 6, 'team_id': self.team.id}
    #         try:
    #             root_instance = ApprovalTemplateTree.objects.get(**root_data)
    #         except Exception as e:
    #             root_instance = ApprovalTemplateTree.objects.create(**root_data)
    #
    #         tree_list = self.get_template_data(template_data, root_instance)
    #
    #         # 创建树节点
    #         for data in tree_list:
    #             data['team_id'] = self.team.id
    #             data['tree_id'] = root_instance.tree_id
    #             try:
    #                 ApprovalTemplateTree.objects.get(id=data['id'], tree_id=root_instance.tree_id)
    #             except Exception as e:
    #                 ApprovalTemplateTree.objects.create(**data)
    #     return template_data

    # 获取审批流程
    # def create_approval_process(self, spno, template_id):
    #     '''创建审批流程'''
    #     appproval_data = self.get_applyDetail(spno)
    #     if not appproval_data:
    #         return None
    #     '''存储审批流程信息'''
    #     sp_record = appproval_data['info']['sp_record']
    #     sp_name = appproval_data['info']['sp_name']
    #     step_number = 1
    #     with transaction.atomic():
    #
    #         # 创建审批流程
    #         process, is_create = ApprovalProcess.objects.get_or_create(template_id=template_id, name=f'{sp_name}流程',
    #                                                                    team_id=self.team.id)
    #
    #         template, is_create = ApprovalTemplate.objects.get_or_create(template_id=template_id, process=process,
    #                                                                      team_id=self.team.id)
    #         u_id = template.user_id
    #         s_id = template.step_id
    #
    #         old_step_list = list(ApprovalStep.objects.filter(process=process).values_list('id', flat=True))
    #         new_step_list = []
    #         # 创建审批步骤和相关用户
    #         for record in sp_record:
    #             step_name = f'{sp_name}第{step_number}审批'
    #             step, is_ok = ApprovalStep.objects.get_or_create(name=step_name, level=step_number, process=process,
    #                                                              team_id=1)
    #             step.approverattr = record.get('approverattr')
    #             step.save()
    #
    #             new_step_list.append(step.id)
    #             old_user_list = list(ApprovalStepUser.objects.filter(step = step).values_list('user_id', flat=True))
    #             new_user_list = []
    #
    #             for detail in record.get('details', []):
    #                 userid = detail['approver']['userid']
    #                 #  查询数据库是否存在，如果不存在则企业微信获取添加
    #                 try:
    #                     user = ApprovalUser.objects.get(user_id=userid)
    #                     name = user.name
    #                 except:
    #                     user = self.get_user(userid)
    #                     name = user['name']
    #                 # 存储用户并创建审批步骤
    #                 user, created_user = ApprovalUser.objects.get_or_create(userid=userid, name=name, team_id=1)
    #                 ApprovalStepUser.objects.get_or_create(user=user, step=step, team_id=1)
    #                 new_user_list.append(user.id)
    #             # 删除修改后的用户
    #             list_difference = [item for item in old_user_list if item not in new_user_list]
    #             if list_difference:
    #                 ApprovalStepUser.objects.filter(step=step, user_id__in=list_difference).delete()
    #             if u_id in list_difference:
    #                 template.step = None
    #                 template.user = None
    #                 template.save()
    #             step_number += 1
    #
    #         # 删除修改后的步骤
    #         list_difference = [item for item in old_step_list if item not in new_step_list]
    #         if list_difference:
    #             ApprovalStep.objects.filter(process=process, id__in=list_difference).delete()
    #
    #         if s_id  in list_difference:
    #             template.step = None
    #             template.user =None
    #             template.save()
    #
    #
    #     return appproval_data


class ParseData:
    def __init__(self, data, request, template_obj):
        '''data：详情数据'''
        self.data = data
        self.request = request
        self.template_obj = template_obj

    def parse_content(self):
        '''控件或选项对应的id---->值'''
        contents = self.data['info']['apply_data']['contents']
        # 判断企业微信传递了哪一个控件和值
        dic = {}
        for content in contents:
            content_id = content['id']
            control = content['control']
            if control == 'Selector':
                options = content['value']['selector']['options']
                for option in options:
                    option_id = option['key']
                    value = option['value'][0]['text']
                    if value:
                        dic[option_id] = value
            elif control == 'Number':
                value = content['value']['new_number']
                if value:
                    dic[content_id] = value
            elif control == 'Money':
                value = content['value']['new_money']
                if value:
                    dic[content_id] = value
            elif control == 'Text':
                value = content['value']['text']
                if value:
                    dic[content_id] = value
            elif control == 'Textarea':
                value = content['value']['text']
                if value:
                    dic[content_id] = value
            elif control == 'Tips':
                value = content['value']['tips']
                if value:
                    dic[content_id] = value
        return dic

    def goods_quantity(self, goods_list):
        # 创建一个字典，用于存储合并后的结果
        combined_goods = defaultdict(lambda: {'quantity': 0})
        # 遍历列表，合并具有相同 'goods' 的项，并将 'quantity' 相加
        for item in goods_list:
            goods_id = item['goods']
            quantity = int(item['quantity']) if isinstance(item['quantity'], str) and item[
                'quantity'].isdigit() else int(
                item['quantity'])
            combined_goods[goods_id]['quantity'] += quantity
            combined_goods[goods_id].update({k: v for k, v in item.items() if k != 'quantity'})  # 保留其他属性

        # 将字典转换回列表
        return list(combined_goods.values())

    # def get_good_item(self):
    #     '''处理商品编号、数量、价格关系'''
    #     data = self.data
    #     if not data:
    #         return None
    #     # 找到根节点
    #     template_root_node = ApprovalTemplateTree.objects.get(id=self.data['info']['template_id'])
    #     # 获取所有节点
    #     all_node = template_root_node.get_descendants(include_self=True)
    #     # 获取数量节点，用于配置数量
    #     number_nodes = all_node.filter(to_type=3)
    #     dic = self.parse_content()
    #
    #     # 寻找数量控件
    #     number_dic = {}
    #     for number_node in number_nodes:
    #         value = dic.get(number_node.id)
    #         setattr(number_node, 'quirenty', value)
    #
    #         if value:
    #             parent_node = number_node.parent
    #             if parent_node.parent is None:
    #                 break
    #             setattr(number_node, 'quirenty', value)
    #             nodes = parent_node.get_descendants(include_self=True)
    #             for node in nodes:
    #                 if node.id != number_node.id:
    #                     number_dic[node.id] = value
    #
    #     # 添加数量关系，返回
    #     tree_list = []
    #     for node in all_node:
    #         id = node.id
    #         if dic.get(id):
    #             if number_dic.get(id):
    #                 quantity = number_dic.get(id)
    #                 tree_list.append({"id": node.id,
    #                                   'value': node.title,
    #                                   'quantity': quantity,
    #                                   'to_type': node.to_type,
    #                                   'to_number': node.to_number})
    #             else:
    #                 tree_list.append({"id": node.id,
    #                                   'value': dic.get(id),
    #                                   'quantity': 1,
    #                                   'to_type': node.to_type,
    #                                   'to_number': node.to_number})
    #
    #     # 添加产品数量
    #     goods_list = []
    #     for tree in tree_list:
    #         if tree.get('to_type') == 1:
    #             goods = Goods.objects.get(id=tree.get('to_number'))
    #             goods_list.append(
    #                 {'goods': goods.id, 'quantity': int(tree.get('quantity')), 'retail_price': goods.retail_price,
    #                  'purchase_price': goods.purchase_price})
    #         elif tree.get('to_type') == 2:
    #             quantity = tree.get('quantity')
    #             salepackage_id = tree.get('to_number')
    #             package_products = SalepackageProducts.objects.filter(salepackage_id=salepackage_id)
    #             for package_product in package_products:
    #                 goods = package_product.goods
    #                 goods_list.append(
    #                     {'goods': goods.id, 'quantity': int(quantity) * int(package_product.quantity),
    #                      'retail_price': goods.retail_price, 'purchase_price': goods.purchase_price})
    #
    #     # goods_list = self.goods_quantity(goods_list)
    #     # 定制品替换
    #     custom_nodes = all_node.filter(to_type=5)
    #     for custom_node in custom_nodes:
    #         if dic.get(custom_node.id):
    #             item_updated = False
    #             approval_custom = ApprovalCustom.objects.get(id=custom_node.to_number)
    #             for good_item in goods_list:
    #                 if good_item['goods'] == approval_custom.original_id:
    #                     good_item['goods'] = approval_custom.current_id
    #                     good_item['retail_price'] = approval_custom.current.retail_price
    #                     good_item['purchase_price'] = approval_custom.current.purchase_price
    #                     good_item['quantity'] = number_dic.get(custom_node.id, 1)
    #                     item_updated = True
    #                     break
    #
    #             if not item_updated:
    #                 quantity = number_dic.get(custom_node.id)
    #                 retail_price = approval_custom.current.retail_price if approval_custom.current.retail_price is not None else 0
    #                 purchase_price = approval_custom.current.purchase_price if approval_custom.current.purchase_price is not None else 0
    #
    #                 goods_list.append({'goods': approval_custom.current_id,
    #                                    'quantity': quantity if quantity is not None else 0,
    #                                    'retail_price': retail_price,
    #                                    'purchase_price': purchase_price
    #                                    })
    #     goods_list = self.goods_quantity(goods_list)
    #     # 处理金额
    #     money = {}
    #     money_nodes = all_node.filter(to_type=4)
    #     for money_node in money_nodes:
    #         if money_node.to_number == 1:
    #             money['total_amount'] = dic.get(money_node.id)
    #         elif money_node.to_number == 2:
    #             money['collection_amount'] = dic.get(money_node.id)
    #         elif money_node.to_number == 3:
    #             money['total_amount'] = dic.get(money_node.id)
    #         elif money_node.to_number == 4:
    #             money['payment_amount'] = dic.get(money_node.id)
    #
    #     other = {}
    #     other_nodes = all_node.filter(to_type=7)
    #     for other_node in other_nodes:
    #         other['store_name'] = dic.get(other_node.id)
    #         break
    #
    #     other_nodes = all_node.filter(to_type=8)
    #     for other_node in other_nodes:
    #         other['store_id'] = dic.get(other_node.id)
    #         break
    #
    #     other_nodes = all_node.filter(to_type=9)
    #     s = {}
    #     for other_node in other_nodes:
    #         if dic.get(other_node.id):
    #             if other_node.title == dic.get(other_node.id):
    #                 try:
    #                     node = other_node.parent
    #                     s[node.title] = dic.get(other_node.id)
    #                 except:
    #                     pass
    #             else:
    #                 s[other_node.title] = dic.get(other_node.id)
    #
    #     other['remark'] = s
    #
    #     return {'good_items': goods_list, 'money': money, 'other': other}

    # def is_approval(self):
    #     # user = lidong
    #     step = 1
    #     print(self.data)
    #     try:
    #         level = step.level
    #         approverattr = step.approverattr
    #     except:
    #         return False
    #
    #     try:
    #         user_id = user.userid
    #     except:
    #         user_id = None
    #
    #     if not user_id:
    #         return None
    #
    #     a_time = 0
    #     max_value = 0
    #     sp_records = self.data.get('info').get('sp_record')
    #
    #     # 遍历流程节点
    #     for sp_record in sp_records:
    #         details = sp_record.get('details', [])
    #         # 遍历步骤中的用户
    #         for detail in details:
    #             approver_userid = detail.get('approver', {}).get('userid')
    #             sp_status = detail.get('sp_status')
    #             sptime = detail.get('sptime')
    #             max_value = max(max_value, sptime)
    #             if approver_userid == user_id:
    #                 a_time = sptime
    #                 a_status = sp_status
    #
    #
    #     return False
    #
    #
    # # def save_data(self):
    #     if not self.is_approval():
    #         # 判断erp配置指定审批人或节点
    #         return None
    #
    #
    #     '''生成入库出库数据'''
    #     logger.info("开始生成入库出库数据")
    #     items = self.get_good_item
    #     if not items:
    #         return None
    #     good_items = items.get('good_items')
    #     money = items.get('money')
    #     other = items.get('other')
    #     result = {}
    #     #  销售单
    #     if self.template_obj.approvaltype == 1:
    #         result['other'] = other
    #         result['number'] = SalesOrder.get_number(self.request.user.team)
    #         result['sales_goods_items'] = []
    #         result['client'] = settings.CLIENT_ID
    #         key_price = 'sales_price'
    #         key_quantity = 'sales_quantity'
    #     # 出库单
    #     elif self.template_obj.approvaltype == 2:
    #         result['number'] = PurchaseOrder.get_number(self.request.user.team)
    #         result['supplier'] = settings.SUPPLIER_ID
    #         result['purchase_goods_items'] = []
    #         key_price = 'purchase_price'
    #         key_quantity = 'purchase_quantity'
    #     else:
    #         return None
    #
    #     # 公共部分设置
    #     result['handle_time'] = timezone.now().strftime("%Y-%m-%d")
    #     result['handler'] = settings.HANDLER_ID
    #     result['other_amount'] = settings.OTHER_AMOUNT
    #     result['warehouse'] = settings.WAEREHOUSE_ID
    #
    #     # 共同的新字典逻辑
    #     new_dicts = []
    #     for item in good_items:
    #         new_item = {}
    #         for key, value in item.items():
    #             if key == 'retail_price':
    #                 new_item[key_price] = value
    #             elif key == 'quantity':
    #                 new_item[key_quantity] = value
    #             elif key == 'goods':
    #                 new_item['goods'] = value
    #         new_dicts.append(new_item)
    #
    #     # 没有数据，不存储。防止传递空模板
    #     if not new_dicts:
    #         return None
    #
    #     # 判断入库还是出库
    #     if self.template_obj.approvaltype == 1:
    #         result['sales_goods_items'] = new_dicts
    #         serializer = SalesOrderSerializer(data=result, context={'request': self.request})
    #     elif self.template_obj.approvaltype == 2:
    #         result['purchase_goods_items'] = new_dicts
    #         serializer = PurchaseOrderSerializer(data=result, context={'request': self.request})
    #     else:
    #         return None
    #
    #     if serializer.is_valid():
    #         instance = serializer.save()  # 调用视图集的 perform_create 方法
    #
    #         # 存储金额
    #         for key, val in money.items():
    #             setattr(instance, key, val)
    #
    #         # 保存所有金额更改后的实例到数据库
    #         instance.save()
    #     # 存储到mongodb
    #     try:
    #         Approval(data=self.data).save()
    #     except Exception as e:
    #         logger.error(f'mongodb存储错误 {e}')
    #     logger.info("生成入库出库数据成功")
    #     return 1
